package com.deepwiki.service;

import com.deepwiki.domain.entity.DocumentCatalog;
import com.deepwiki.dto.DirectoryTreeNode;
import com.deepwiki.storage.impl.ElasticsearchStorageStrategy;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 目录树服务 - 修正版
 * 支持新的ES索引结构，从ES获取catalog数据
 */
@Service
public class DirectoryTreeService {

    private static final Logger logger = LoggerFactory.getLogger(DirectoryTreeService.class);

    private final ElasticsearchStorageStrategy elasticsearchStorage;
    private final ObjectMapper objectMapper;

    @Autowired
    public DirectoryTreeService(ElasticsearchStorageStrategy elasticsearchStorage,
                               ObjectMapper objectMapper) {
        this.elasticsearchStorage = elasticsearchStorage;
        this.objectMapper = objectMapper;
    }

    /**
     * 根据仓库ID生成目录树JSON文件
     *
     * @param warehouseId 仓库ID
     * @return 目录树JSON文件路径
     */
    public String generateDirectoryTree(String warehouseId) {
        try {
            logger.info("开始生成目录树: {}", warehouseId);
            
            // 从ES获取文档目录 - 使用新的ES索引结构
            List<ElasticsearchStorageStrategy.CatalogInfo> catalogInfos = getCatalogsFromElasticsearch(warehouseId);
            
            if (catalogInfos.isEmpty()) {
                logger.warn("未找到仓库的文档目录: {}", warehouseId);
                return null;
            }
            
            // 转换为DocumentCatalog对象以兼容现有逻辑
            List<DocumentCatalog> catalogs = convertToDocumentCatalogs(catalogInfos);
            
            // 构建目录树
            List<DirectoryTreeNode> rootNodes = buildDirectoryTree(catalogs);
            
            // 转换为JSON
            String jsonContent = objectMapper.writeValueAsString(rootNodes);
            
            // 这个方法现在主要用于兼容性，实际的文档目录结构已经在DocumentGenerationService中生成并保存
            logger.info("目录树生成完成: {}, 保存到ES", warehouseId);
            return "ES:" + warehouseId + "/directory-tree";
            
        } catch (Exception e) {
            logger.error("生成目录树失败: {}", warehouseId, e);
            throw new RuntimeException("生成目录树失败: " + e.getMessage(), e);
        }
    }

    /**
     * 从ES获取文档目录列表
     */
    private List<ElasticsearchStorageStrategy.CatalogInfo> getCatalogsFromElasticsearch(String warehouseId) {
        try {
            return elasticsearchStorage.getCatalogsByWarehouse(warehouseId);
        } catch (Exception e) {
            logger.error("从ES获取catalog数据失败: {}", warehouseId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 转换CatalogInfo为DocumentCatalog以兼容现有逻辑
     */
    private List<DocumentCatalog> convertToDocumentCatalogs(List<ElasticsearchStorageStrategy.CatalogInfo> catalogInfos) {
        return catalogInfos.stream().map(catalogInfo -> {
            DocumentCatalog catalog = new DocumentCatalog();
            catalog.setId(catalogInfo.catalogId);
            catalog.setWarehouseId(catalogInfo.warehouseId);
            catalog.setDucumentId(catalogInfo.documentId);
            catalog.setParentId(catalogInfo.parentId);
            catalog.setName(catalogInfo.name);
            catalog.setUrl(catalogInfo.url);
            catalog.setDescription(catalogInfo.description);
            catalog.setOrderIndex(catalogInfo.orderIndex);
            catalog.setIsCompleted(catalogInfo.isCompleted);
            catalog.setIsDeleted(catalogInfo.isDeleted);
            catalog.setPrompt(catalogInfo.prompt);
            catalog.setDependentFile(catalogInfo.dependentFile);
            return catalog;
        }).collect(Collectors.toList());
    }

    /**
     * 读取目录树 - 从ES仓库的documentTreeStructure字段获取
     *
     * @param warehouseId 仓库ID
     * @return 目录树节点列表
     */
    public List<DirectoryTreeNode> getDirectoryTree(String warehouseId) {
        try {
            // 从ES仓库记录中读取文档目录结构
            String documentTreeJson = getDocumentTreeStructureFromWarehouse(warehouseId);
            
            if (documentTreeJson == null || documentTreeJson.trim().isEmpty()) {
                logger.info("文档目录结构不存在，尝试从catalog数据构建: {}", warehouseId);
                return buildDirectoryTreeFromCatalogs(warehouseId);
            }
            
            // 解析文档目录结构JSON
            return parseDocumentTreeStructure(documentTreeJson);
            
        } catch (Exception e) {
            logger.error("读取目录树失败: {}", warehouseId, e);
            throw new RuntimeException("读取目录树失败: " + e.getMessage(), e);
        }
    }

    /**
     * 从ES仓库记录中获取文档目录结构
     */
    private String getDocumentTreeStructureFromWarehouse(String warehouseId) {
        try {
            return elasticsearchStorage.getDocumentTreeStructure(warehouseId);
        } catch (Exception e) {
            logger.error("从ES获取文档目录结构失败: {}", warehouseId, e);
            return null;
        }
    }

    /**
     * 解析文档目录结构JSON
     */
    private List<DirectoryTreeNode> parseDocumentTreeStructure(String documentTreeJson) {
        try {
            // 解析生成的文档目录结构JSON
            Map<String, Object> treeRoot = objectMapper.readValue(documentTreeJson, Map.class);
            
            if (treeRoot.containsKey("children")) {
                List<Map<String, Object>> children = (List<Map<String, Object>>) treeRoot.get("children");
                return convertToDirectoryTreeNodes(children);
            }
            
            return new ArrayList<>();
            
        } catch (Exception e) {
            logger.error("解析文档目录结构JSON失败", e);
            return new ArrayList<>();
        }
    }

    /**
     * 将Map结构转换为DirectoryTreeNode
     */
    private List<DirectoryTreeNode> convertToDirectoryTreeNodes(List<Map<String, Object>> nodeList) {
        List<DirectoryTreeNode> nodes = new ArrayList<>();
        
        for (Map<String, Object> nodeMap : nodeList) {
            DirectoryTreeNode node = new DirectoryTreeNode();
            node.setId((String) nodeMap.get("id"));
            node.setName((String) nodeMap.get("name"));
            node.setUrl((String) nodeMap.get("url"));
            node.setDescription((String) nodeMap.get("description"));
            node.setType((String) nodeMap.get("type"));
            node.setIsGenerated((Boolean) nodeMap.get("isGenerated"));
            
            if (nodeMap.get("orderIndex") instanceof Integer) {
                node.setOrderIndex((Integer) nodeMap.get("orderIndex"));
            }
            
            // 递归处理子节点
            if (nodeMap.containsKey("children")) {
                List<Map<String, Object>> children = (List<Map<String, Object>>) nodeMap.get("children");
                if (children != null && !children.isEmpty()) {
                    List<DirectoryTreeNode> childNodes = convertToDirectoryTreeNodes(children);
                    node.setChildren(childNodes);
                }
            }
            
            nodes.add(node);
        }
        
        return nodes;
    }

    /**
     * 从catalog数据构建目录树（备用方法）
     */
    private List<DirectoryTreeNode> buildDirectoryTreeFromCatalogs(String warehouseId) {
        try {
            // 从ES获取文档目录
            List<ElasticsearchStorageStrategy.CatalogInfo> catalogInfos = getCatalogsFromElasticsearch(warehouseId);
            
            if (catalogInfos.isEmpty()) {
                return new ArrayList<>();
            }
            
            // 转换为DocumentCatalog对象
            List<DocumentCatalog> catalogs = convertToDocumentCatalogs(catalogInfos);
            
            // 构建目录树
            return buildDirectoryTree(catalogs);
            
        } catch (Exception e) {
            logger.error("从catalog数据构建目录树失败: {}", warehouseId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 更新目录树（当文档目录发生变化时）
     *
     * @param warehouseId 仓库ID
     */
    public void updateDirectoryTree(String warehouseId) {
        try {
            logger.info("更新目录树: {}", warehouseId);
            generateDirectoryTree(warehouseId);
        } catch (Exception e) {
            logger.error("更新目录树失败: {}", warehouseId, e);
            throw new RuntimeException("更新目录树失败: " + e.getMessage(), e);
        }
    }

    /**
     * 删除目录树文件
     *
     * @param warehouseId 仓库ID
     */
    public void deleteDirectoryTree(String warehouseId) {
        try {
            logger.info("删除目录树: {}", warehouseId);
            
            // 从ES仓库记录中清除目录树数据
            elasticsearchStorage.saveDirectoryTree(warehouseId, "");
            
            logger.info("目录树删除完成: {}", warehouseId);
            
        } catch (Exception e) {
            logger.error("删除目录树失败: {}", warehouseId, e);
            throw new RuntimeException("删除目录树失败: " + e.getMessage(), e);
        }
    }

    /**
     * 构建目录树结构
     *
     * @param catalogs 文档目录列表
     * @return 目录树根节点列表
     */
    private List<DirectoryTreeNode> buildDirectoryTree(List<DocumentCatalog> catalogs) {
        try {
            if (catalogs.isEmpty()) {
                return new ArrayList<>();
            }
            
            // 过滤掉已删除的目录
            List<DocumentCatalog> activeCatalogs = catalogs.stream()
                    .filter(catalog -> !catalog.getIsDeleted())
                    .collect(Collectors.toList());
            
            // 按orderIndex排序
            activeCatalogs.sort(Comparator.comparing(DocumentCatalog::getOrderIndex, Comparator.nullsLast(Integer::compareTo)));
            
            // 构建ID到目录的映射
            Map<String, DocumentCatalog> catalogMap = activeCatalogs.stream()
                    .collect(Collectors.toMap(DocumentCatalog::getId, catalog -> catalog));
            
            // 查找根节点（没有父级的节点）
            List<DocumentCatalog> rootCatalogs = activeCatalogs.stream()
                    .filter(catalog -> catalog.getParentId() == null || catalog.getParentId().trim().isEmpty())
                    .collect(Collectors.toList());
            
            // 如果没有找到根节点，将所有节点作为根节点处理
            if (rootCatalogs.isEmpty()) {
                rootCatalogs = activeCatalogs;
            }
            
            // 递归构建树结构
            List<DirectoryTreeNode> rootNodes = new ArrayList<>();
            for (DocumentCatalog rootCatalog : rootCatalogs) {
                DirectoryTreeNode rootNode = buildTreeNode(rootCatalog, catalogMap, activeCatalogs);
                rootNodes.add(rootNode);
            }
            
            return rootNodes;
            
        } catch (Exception e) {
            logger.error("构建目录树结构失败", e);
            return new ArrayList<>();
        }
    }

    /**
     * 递归构建树节点
     *
     * @param catalog 当前目录
     * @param catalogMap 目录映射
     * @param allCatalogs 所有目录列表
     * @return 树节点
     */
    private DirectoryTreeNode buildTreeNode(DocumentCatalog catalog, Map<String, DocumentCatalog> catalogMap, 
                                          List<DocumentCatalog> allCatalogs) {
        DirectoryTreeNode node = new DirectoryTreeNode();
        node.setId(catalog.getId());
        node.setName(catalog.getName());
        node.setUrl(catalog.getUrl());
        node.setDescription(catalog.getDescription());
        node.setOrderIndex(catalog.getOrderIndex());
        node.setIsGenerated(catalog.getIsCompleted()); // 映射字段名
        node.setType("folder"); // 默认类型
        
        // 查找子节点
        List<DocumentCatalog> children = allCatalogs.stream()
                .filter(c -> catalog.getId().equals(c.getParentId()))
                .sorted(Comparator.comparing(DocumentCatalog::getOrderIndex, Comparator.nullsLast(Integer::compareTo)))
                .collect(Collectors.toList());
        
        if (!children.isEmpty()) {
            List<DirectoryTreeNode> childNodes = new ArrayList<>();
            for (DocumentCatalog child : children) {
                DirectoryTreeNode childNode = buildTreeNode(child, catalogMap, allCatalogs);
                childNodes.add(childNode);
            }
            node.setChildren(childNodes);
        }
        
        return node;
    }

    /**
     * 验证目录树结构的有效性
     *
     * @param warehouseId 仓库ID
     * @return 验证结果
     */
    public boolean validateDirectoryTree(String warehouseId) {
        try {
            List<DirectoryTreeNode> tree = getDirectoryTree(warehouseId);
            
            if (tree == null || tree.isEmpty()) {
                logger.warn("目录树为空或不存在: {}", warehouseId);
                return false;
            }
            
            // 递归验证每个节点
            for (DirectoryTreeNode node : tree) {
                if (!validateNode(node)) {
                    return false;
                }
            }
            
            logger.info("目录树验证通过: {}", warehouseId);
            return true;
            
        } catch (Exception e) {
            logger.error("验证目录树失败: {}", warehouseId, e);
            return false;
        }
    }

    /**
     * 递归验证节点
     */
    private boolean validateNode(DirectoryTreeNode node) {
        if (node == null || node.getId() == null || node.getName() == null) {
            logger.warn("发现无效节点: {}", node);
            return false;
        }
        
        if (node.getChildren() != null) {
            for (DirectoryTreeNode child : node.getChildren()) {
                if (!validateNode(child)) {
                    return false;
                }
            }
        }
        
        return true;
    }

    /**
     * 获取目录树统计信息
     *
     * @param warehouseId 仓库ID
     * @return 统计信息
     */
    public Map<String, Object> getDirectoryTreeStats(String warehouseId) {
        try {
            List<DirectoryTreeNode> tree = getDirectoryTree(warehouseId);
            
            Map<String, Object> stats = new HashMap<>();
            stats.put("totalNodes", countNodes(tree));
            stats.put("maxDepth", calculateMaxDepth(tree));
            stats.put("generatedNodes", countGeneratedNodes(tree));
            stats.put("rootNodes", tree.size());
            
            return stats;
            
        } catch (Exception e) {
            logger.error("获取目录树统计信息失败: {}", warehouseId, e);
            return new HashMap<>();
        }
    }

    /**
     * 计算节点总数
     */
    private int countNodes(List<DirectoryTreeNode> nodes) {
        if (nodes == null || nodes.isEmpty()) {
            return 0;
        }
        
        int count = nodes.size();
        for (DirectoryTreeNode node : nodes) {
            if (node.getChildren() != null) {
                count += countNodes(node.getChildren());
            }
        }
        
        return count;
    }

    /**
     * 计算最大深度
     */
    private int calculateMaxDepth(List<DirectoryTreeNode> nodes) {
        if (nodes == null || nodes.isEmpty()) {
            return 0;
        }
        
        int maxDepth = 1;
        for (DirectoryTreeNode node : nodes) {
            if (node.getChildren() != null) {
                int childDepth = 1 + calculateMaxDepth(node.getChildren());
                maxDepth = Math.max(maxDepth, childDepth);
            }
        }
        
        return maxDepth;
    }

    /**
     * 计算已生成的节点数
     */
    private int countGeneratedNodes(List<DirectoryTreeNode> nodes) {
        if (nodes == null || nodes.isEmpty()) {
            return 0;
        }
        
        int count = 0;
        for (DirectoryTreeNode node : nodes) {
            if (Boolean.TRUE.equals(node.getIsGenerated())) {
                count++;
            }
            if (node.getChildren() != null) {
                count += countGeneratedNodes(node.getChildren());
            }
        }
        
        return count;
    }
} 